package com.youlu.campus.admin.auth.controller;

import com.alibaba.fastjson.JSON;
import com.youlu.campus.admin.auth.dto.RoleQueryRequest;
import com.youlu.campus.admin.auth.dto.UserInfoDto;
import com.youlu.campus.admin.auth.dto.UserQueryRequest;
import com.youlu.campus.admin.auth.dto.UserUpdateForm;
import com.youlu.campus.admin.auth.entity.SystemResource;
import com.youlu.campus.admin.auth.entity.SystemRole;
import com.youlu.campus.admin.auth.entity.SystemRoleResouce;
import com.youlu.campus.admin.auth.entity.SystemRoleUser;
import com.youlu.campus.admin.auth.entity.SystemUser;
import com.youlu.campus.admin.auth.entity.exception.AuthErrorCode;
import com.youlu.campus.admin.auth.service.PasswordService;
import com.youlu.campus.admin.auth.service.ResourceService;
import com.youlu.campus.admin.auth.service.RoleService;
import com.youlu.campus.admin.auth.service.RsaService;
import com.youlu.campus.admin.auth.service.UserService;
import com.youlu.campus.admin.auth.vo.RoleVo;
import com.youlu.campus.admin.auth.vo.UserCreateRequest;
import com.youlu.campus.admin.utils.AuthUtils;
import com.youlu.campus.common.base.RestResult;
import com.youlu.campus.common.base.RestResultBuilder;
import com.youlu.campus.common.exception.BusinessException;
import com.youlu.campus.common.model.GlobalErrorCode;
import com.youlu.campus.common.utils.BeanMapperUtils;
import com.youlu.campus.common.utils.ExceptionUtils;
import com.youlu.campus.common.utils.ValidatorUtils;
import com.youlu.campus.entity.system.SystemResourceDto;
import com.youlu.campus.entity.system.UserDataPermission;
import com.youlu.campus.service.system.UserDataPermissionService;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 用户管理
 */
@RestController
public class UserRestController {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private UserService userService;

    @Autowired
    PasswordService passwordService;

    @Autowired
    RsaService rsaService;


    @Autowired
    private Environment env;
    @Autowired
    private RoleService roleService;
    @Autowired
    private ResourceService resourceService;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private UserDataPermissionService userDataPermissionService;


    private static final String IMG_REX = ".*(.jpeg|.jpg|.png|.gif|.bmp)$";

    private static final int IMG_SIZE = 1024 * 1024;

    @GetMapping("/user/pwd/batch-update")
    public RestResult batchUpdatePwd(@RequestParam("systemAppId") String systemAppId) {
        String comId = AuthUtils.getComId();
        userService.batchModifyPassword(systemAppId);
        return RestResultBuilder.builder().success().data("ok").build();
    }

    @GetMapping("/user/pwd/re-batch-update")
    public RestResult reBatchUpdatePwd(@RequestParam("systemAppId") String systemAppId) {
        String comId = AuthUtils.getComId();
        userService.reBatchUpdatePwd(systemAppId);
        return RestResultBuilder.builder().success().data("ok").build();
    }

    @PostMapping("/user/list")
    public RestResult getUsers(@RequestBody @Valid UserQueryRequest userQueryRequest) {
        String comId = AuthUtils.getComId();
        userQueryRequest.setTenantId(comId);
        Page<SystemUser> users = userService.query(userQueryRequest);
        if (users == null) {
            PageRequest pageRequest = PageRequest.of(userQueryRequest.getPage() - 1, userQueryRequest.getPageSize());
            users = PageableExecutionUtils.getPage(new ArrayList<>(), pageRequest, () -> 0L);
        }
        return RestResultBuilder.builder().success().data(users).build();
    }

    /**
     * 创建用户
     *
     * @param userCreateRequest
     * @return
     */
    @PostMapping("/user/create")
    public RestResult create(@RequestBody @Valid UserCreateRequest userCreateRequest) {
        String domain = AuthUtils.getDomain();
        String comId = AuthUtils.getComId();
        Long currentTime = System.currentTimeMillis();
        //用户密码格式校验
        String currentUserId = AuthUtils.getUserId();
        String encPwd = userCreateRequest.getEncPwd();
//        String pwd = rsaService.decrypt(encPwd, String.valueOf(currentUserId));
        logger.debug("currentUserId:{}, pwd rsa decrypt result:{}", currentUserId, encPwd);

        //密码格式校验是否正确
//        boolean flag = ValidatorUtils.validatePassword(pwd);
//        if (!flag) {
//            logger.warn("UserRestController.updatePwdNoValidateOldPwd flag:{}", flag);
//            ExceptionUtils.business(AuthErrorCode.USER_PASSWORD_FORMAT_ERROR);
//        }
        String loginName = userCreateRequest.getLoginName();
        logger.debug("校验 用户{} 在公司: {}中是否已经存在", loginName, domain);
        if (userService.ifExists(loginName, domain)) {
            logger.error("用户{} 在公司: {}中已经存在", loginName, domain);
            throw new BusinessException(AuthErrorCode.LOGIN_NAME_CONFLICT);
        }

        SystemUser user = new SystemUser();
        BeanUtils.copyProperties(userCreateRequest, user);
        user.setDomain(domain);
        //用户登录密码
        user.setEncPwd(DigestUtils.md5Hex(encPwd));
        user.setEncPwd(encPwd);
        user.setTenantId(comId);
        user.setCreatedTime(new Date());
        user.setRoleId(userCreateRequest.getRoleId());
        if (StringUtils.isNotBlank(userCreateRequest.getRoleId())) {
            SystemRole role = roleService.getById(userCreateRequest.getRoleId(), comId);
            if (Objects.nonNull(role)) {
                user.setRoleName(role.getName());
            }
        }
        if (Objects.isNull(userCreateRequest.getRoleIds())) {
            String[] roleIds = new String[1];
            roleIds[0] = userCreateRequest.getRoleId();
            userCreateRequest.setRoleIds(roleIds);
        }
        userService.create(user, userCreateRequest.getRoleIds(), comId);
        return RestResultBuilder.builder().success().build();
    }

    /**
     * 更新用户信息
     *
     * @param id
     * @param userUpdateForm
     * @return
     */
    @PostMapping("/user/update/{id}")
    public RestResult update(@PathVariable("id") String id, @RequestBody @Valid UserUpdateForm userUpdateForm) {
        String comId = AuthUtils.getComId();
        SystemUser user = new SystemUser();
        BeanUtils.copyProperties(userUpdateForm, user);
        user.setId(id);
        user.setTenantId(comId);
        //查询老的用户
        SystemUser oldUser = mongoTemplate.findById(id, SystemUser.class);
        if (oldUser == null) {
            throw new BusinessException("账户信息不存在");
        }
        if (StringUtils.isNotBlank(userUpdateForm.getRoleId())) {
            SystemRole role = roleService.getById(userUpdateForm.getRoleId(), comId);
            if (Objects.nonNull(role)) {
                user.setRoleName(role.getName());
            }
            //修改渠道用户角色绑定关系
            Query q1 = new Query();
            q1.addCriteria(Criteria.where("userId").is(id));
            Update up1 = new Update();
            up1.set("roleId", userUpdateForm.getRoleId());
            mongoTemplate.updateFirst(q1, up1, SystemRoleUser.class);

            user.setRoleId(userUpdateForm.getRoleId());
        }
        userService.update(user);
        return RestResultBuilder.builder().success().build();
    }

    @PostMapping("/user/permission/update")
    public RestResult update(@RequestBody UserDataPermission req) {
        String comId = AuthUtils.getComId();
        boolean re = userDataPermissionService.update(req);
        if (re) {
            return RestResultBuilder.builder().success().build();
        }
        return RestResultBuilder.builder().failure().build();
    }

    @GetMapping("/user/permission/find-one")
    public RestResult findOne(@RequestParam("userId") String userId) {
        String comId = AuthUtils.getComId();
        return RestResultBuilder.builder().success(userDataPermissionService.findOne(userId)).build();
    }

    @GetMapping("/user/delete/{id}")
    public RestResult delete(@PathVariable String id) {
        String comId = AuthUtils.getComId();
        userService.delete(id, comId);
        logger.debug("删除用户: {} 成功 继续删除分组中的用户信息", id);
        return RestResultBuilder.builder().success().build();
    }

    @GetMapping("/user/{id}")
    public RestResult get(@PathVariable String id) {
        logger.debug("id:{}", id);
        HashMap<String, Object> map = new HashMap<>();
        SystemUser user = userService.get(id);
        if (user == null) {
            logger.error(":>>> 用户:{} 不存在", id);
            throw new BusinessException(AuthErrorCode.USER_NOT_LOGIN);
        }
        map.put("user", user);
        List<SystemRole> roleList = roleService.listRole(AuthUtils.getUserId(), AuthUtils.getComId());
        if (roleList != null && !roleList.isEmpty()) {
            map.put("roleId", roleList.get(0).getId());
        }
        logger.debug("return user:{}", JSON.toJSONString(map));
        return RestResultBuilder.builder().success(map).build();
    }


    /**
     * 当前用户修改自己登录密码
     *
     * @param userId
     * @param map
     * @return
     */
    @PostMapping("/user/pwd/{id}")
    public RestResult updatePwd(@PathVariable("id") String userId, @RequestBody
    Map<String, String> map) {

        userId = AuthUtils.getUserId();  //从登录信息中获取自己的密码
        String comId = AuthUtils.getComId();
        String password = map.get("newPwd");
        String oldPassword = map.get("oldPwd");

        String currentUserId = AuthUtils.getUserId();
        String pwd = rsaService.decrypt(password, String.valueOf(currentUserId));
        logger.debug("currentUserId:{}, pwd rsa decrypt result:{}", currentUserId, pwd);

        //密码格式校验是否正确
        boolean flag = ValidatorUtils.validatePassword(pwd);
        if (!flag) {
            logger.warn("UserRestController.updatePwdNoValidateOldPwd flag:{}", flag);
            ExceptionUtils.business(AuthErrorCode.USER_PASSWORD_FORMAT_ERROR);
        }

        String md5EncPwd = DigestUtils.md5Hex(pwd);

        if (userService.updatePwd(userId, comId, md5EncPwd, oldPassword)) {
            return RestResultBuilder.builder().success().build();
        }

        return RestResultBuilder.builder().failure().build();
    }

    /**
     * 修改密码
     *
     * @param userId     修改密码
     * @param requestMap
     * @return
     */
    @PostMapping("/user/update/pwd/{id}")
    public RestResult updatePwdNoValidateOldPwd(@PathVariable("id") String userId,
                                                @RequestBody Map<String, String> requestMap) {
        logger.debug("UserRestController.updatePwdNoValidateOldPwd paras userId:{}, requestMap:{}",
                userId, JSON.toJSONString(requestMap));
        String encPwd = requestMap.get("encPwd");
        if (StringUtils.isEmpty(encPwd)) {
            logger.error("密码为空");
            throw new BusinessException(GlobalErrorCode.BAD_REQUEST);
        }
        String comId = AuthUtils.getComId();
        boolean result = userService.updatePwd(userId, comId, encPwd);
        return RestResultBuilder.builder().success(result).build();
//        String pwd = rsaService.decrypt(encPwd, String.valueOf(currentUserId));
//        logger.debug("currentUserId:{}, pwd rsa decrypt result:{}", currentUserId, pwd);
//
//        //密码格式校验是否正确
//        boolean flag = ValidatorUtils.validatePassword(pwd);
//        if (!flag) {
//            logger.warn("UserRestController.updatePwdNoValidateOldPwd flag:{}", flag);
//            ExceptionUtils.business(AuthErrorCode.USER_PASSWORD_FORMAT_ERROR);
//        }
//
//        String md5EncPwd = DigestUtils.md5Hex(pwd);
//        boolean result = userService.updatePwd(userId, comId, md5EncPwd);
//        return RestResultBuilder.builder().success(result).build();
    }


    /**
     * 获取角色
     *
     * @return
     */
    @PostMapping("/role/list")
    public RestResult getRoles(@RequestBody RoleQueryRequest roleQueryRequest) {

        String comId = AuthUtils.getComId();
        roleQueryRequest.setTenantId(comId);
        Page<SystemRole> users = roleService.query(roleQueryRequest);
        if (users == null) {
            PageRequest pageRequest = PageRequest.of(roleQueryRequest.getPage() - 1, roleQueryRequest.getPageSize());
            users = PageableExecutionUtils.getPage(new ArrayList<>(), pageRequest, () -> 0L);
        }
        return RestResultBuilder.builder().success().data(users).build();
    }

    /**
     * 创建角色
     *
     * @return
     */
    @PostMapping("/role/create")
    public RestResult createRole(@RequestBody @NotNull RoleVo roleVo) {

        String comId = AuthUtils.getComId();
        roleVo.setTenantId(comId);
        boolean result = roleService.create(roleVo);
        logger.info(":>>> 创建角色结果:{}", result);
        if (result) {
            return RestResultBuilder.builder().success().build();
        }
        return RestResultBuilder.builder().failure().build();
    }

    /**
     * 修改角色
     *
     * @return
     */
    @PostMapping("/role/update")
    public RestResult updateRole(@RequestBody @NotNull RoleVo roleVo) {
        String comId = AuthUtils.getComId();
        roleVo.setTenantId(comId);
        boolean result = roleService.update(roleVo);
        logger.info(":>>> 修改角色结果:{}", result);
        if (result) {
            return RestResultBuilder.builder().success().build();
        }
        return RestResultBuilder.builder().failure().build();
    }

    /**
     * 获取RSA公钥
     *
     * @return
     */
    @GetMapping("/public-key")
    public RestResult publicKey() {
        String userId = AuthUtils.getUserId();
        logger.info(":>>> 开始获取密钥 :{}", userId);
        String publicKey = rsaService.publicKey(userId);
        logger.info("userId:{}, rsa publicKey: {}", userId, publicKey);
        return RestResultBuilder.builder().success(publicKey).build();
    }

    @RequestMapping("/user/info")
    public RestResult userInfo() {
        String userId = AuthUtils.getUserId();
        String comId = AuthUtils.getComId();

        SystemUser user = userService.getUserCache(userId);
        List<SystemRole> roleList = roleService.listRole(AuthUtils.getUserId(), AuthUtils.getComId());
        UserInfoDto dto = BeanMapperUtils.map(user, UserInfoDto.class);
        if (CollectionUtils.isNotEmpty(roleList)) {
            List<SystemRole> myRoleList = roleList.stream().filter(systemRole -> user.getRoleId().equals(systemRole.getId())).collect(Collectors.toList());
            dto.setRoles(myRoleList);
        }

//        List<Menu> menus = resourceService.listMenus(userId, comId);
//        List<String> menuString = new ArrayList<>();
//        if (menus == null) {
//            menus = new ArrayList<>();
//        }
//        for (Menu menu : menus) {
//            if (!menuString.contains(menu.getName())) {
//                menuString.add(menu.getName());
//            }
//            if (menu.getChilds() == null || menu.getChilds().isEmpty()) {
//                continue;
//            }
//            for (Menu menu1 : menu.getChilds()) {
//                if (!menuString.contains(menu1.getName())) {
//                    menuString.add(menu1.getName());
//                }
//            }
//
//        }
//        dto.setMenus(menus);
        dto.setMenusString(getUserMenuIds(comId, userId, user.getRoleId()));
        dto.getMenusString().add("创建证书");
        dto.getMenusString().add("查看备注");
        dto.setFirstLogin(user.getFirstLogin());
        if (Boolean.TRUE.equals(user.getFirstLogin())) {
            userService.updateFirstLogin(user);
        }
        UserDataPermission userDataPermission = userDataPermissionService.findOne(userId);
        logger.info(":>>> 用户信息开始获取数据权限:{},{}", user, userDataPermission == null ? 0 : JSON.toJSON(userDataPermission.getActivityId()));
        if (Objects.nonNull(userDataPermission) && CollectionUtils.isNotEmpty(userDataPermission.getDataPermission())) {
            for (SystemResourceDto systemResourceDto : userDataPermission.getDataPermission()) {
                if (StringUtils.isNotBlank(systemResourceDto.getPermission())) {
                    dto.getButtonPermissions().add(systemResourceDto.getPermission());
                }
            }
        }
        return RestResultBuilder.builder().success(dto).build();
    }

    /**
     * 获取资源
     *
     * @return
     */
    @PostMapping("/resource/list")
    public RestResult getResources(@RequestBody SystemResource req) {

        String comId = AuthUtils.getComId();
        List<SystemResource> datas = resourceService.listByType(comId, req.getType());
        return RestResultBuilder.builder().success().data(datas).build();
    }

    private List<String> getUserMenuIds(String tenantId, String userId, String roleId) {
        logger.info(":>>> 开始获取租户:{},用户:{} 所有菜单,角色:{}", tenantId, userId, roleId);
        List<String> menuString = new ArrayList<>();
        Query query = new Query();
        query.addCriteria(Criteria.where("tenantId").is(tenantId).and("roleId").is(roleId));
        List<SystemRoleResouce> roleResouces = mongoTemplate.find(query, SystemRoleResouce.class);
        if (CollectionUtils.isEmpty(roleResouces)) {
            return Collections.EMPTY_LIST;
        }
        List<String> resourceIds = new ArrayList<>();
        for (SystemRoleResouce systemRoleResouce : roleResouces) {
            resourceIds.add(systemRoleResouce.getResourceId());
        }
        Query query1 = new Query();
        query1.addCriteria(Criteria.where("tenantId").is(tenantId).and("id").in(resourceIds));
        List<SystemResource> res = mongoTemplate.find(query1, SystemResource.class);
//        logger.info(":>>> 系统资源为:{}", JSON.toJSONString(res));
        for (SystemResource systemResource : res) {
//            logger.info(":>>> 资源信息:{},是否为菜单:{}", JSON.toJSONString(systemResource), systemResource.getType().equals(3));
            if (Objects.nonNull(systemResource.getType()) && (systemResource.getType().equals(3) || systemResource.getType().equals(2))) {
                if (!menuString.contains(systemResource.getName())) {
                    menuString.add(systemResource.getName());
                }
            }
        }
        return menuString;

    }

}
